package com.iwop.moto.service.impl;

import com.alibaba.fastjson.JSON;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.iwop.moto.model.*;
import com.iwop.moto.service.*;
import com.iwop.moto.utils.alipay.AliPayUtil;
import com.iwop.moto.utils.stringUtil.*;
import com.iwop.moto.utils.weixin.utils.WxPayUtil;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Created by mobom on 2016/9/30.
 */

@Service
public class MPaymentServiceImpl extends BaseService implements MPaymentService {

    private Logger logger = Logger.getLogger(MPaymentServiceImpl.class);


    @Autowired
    FBillService fBillService;
    @Autowired
    UserService userService;
    @Autowired
    StoreService storeService;
    @Autowired
    MCashBackConfigService mCashBackConfigService;
    @Autowired
    FCashBackRecordService fCashBackRecordService;
    @Autowired
    FPartnerStoreService fPartnerStoreService;

    @Override
    public void insert(MPayment MPayment) {
        String buyerUserId = MPayment.getBuyerUserId();//付款方did
        String outTradeNo = MPayment.getOutTradeNo();//订单号
        Double payMoney = MPayment.getPayMoney();//交易金额
        Double payFee = 0d;
        if (MPayment.getPayFee() == null) {
            payFee = 0d;
        }else {
            payFee = MPayment.getPayFee();//交易手续费}
        }
            double orderMoney = BigDecimalUtil.getAdd(payMoney, payFee);//订单金额
            if (!MPayment.getPayType().equals("Topup")) {
                if (StringUtils.isNotEmpty(buyerUserId) || StringUtils.isNotEmpty(outTradeNo) ||
                        payMoney != null || payFee != null) {
                    userService.userProceeds(buyerUserId, outTradeNo, orderMoney);
                }
            }
            getSqlSession().insert("MPaymentMapper.insert", MPayment);

        //充值不返现
        if (MPayment.getPayType().equals("Topup")){
            return;
        }
            //验证是否当天头两笔

            //查询收款方用户信息 过滤条件出手机
            MPayment payment = this.findPaymentByOutTradeNo(outTradeNo);
            String sellerUserId = payment.getSellerUserId(); //收款方id
            User sellerUserParam = new User();
            sellerUserParam.setSid(sellerUserId);
            User sellerUser = userService.findUserByParam(sellerUserParam);


            //查找维修店
            SuperRecordModel store = new SuperRecordModel();
            store.put("user_id", sellerUserId);
            store = storeService.findStoreByUserId(store);


            //过滤审核通过合伙人
            List<User> sellerUsers = userService.findUsersByTel(sellerUser.getTel());
            String store_user_id = store.get("user_id").toString();
            FPartnerStore fPartnerStore = fPartnerStoreService.searchById(store_user_id); //合伙人-维修店校验
            if (null != fPartnerStore) {
                logger.info(store_user_id + "合伙人维修店不参与返现活动");
                return;
            }

            for (User user : sellerUsers) {
                if (user.getUserType().equals("5") && user.getAuditFlag().equals("2")) {
                    return;
                }
            }

            //买家信息
            User user = new User();
            user.setSid(buyerUserId);
            User buyUser = userService.findUserByParam(user);
            String store_type = store.get("store_type").toString();
            switch (store_type) {
                case "1":
                    logger.info("维修店-用户");
                    if ("popular".equals(buyUser.getUserType())) {
                        cashBackHandle(orderMoney, sellerUserId, outTradeNo, store_type);
                    }
                    break;
                case "2":
                    logger.info("配件店-维修店");
                    if ("1".equals(buyUser.getUserType())) {
                        SuperRecordModel superRecordModel = new SuperRecordModel();
                        superRecordModel.put("user_id", buyUser.getSid());
                        SuperRecordModel storeByUserId = storeService.findStoreByUserId(superRecordModel);
                        if (!storeByUserId.getString("store_type").equals("1")) {
                            break;
                        }
                        sparepart2repair(orderMoney, sellerUserId, outTradeNo, store_type);
                    }
                    break;
                case "3":
                    logger.info("整车店-用户");
                    if ("popular".equals(buyUser.getUserType())) {
                        sale2User(orderMoney, sellerUserId, outTradeNo, store_type);
                    }
                    break;
                default:
                    logger.info("维修店没有找到相关类型");
            }

        }


    /**
     * 维修店-用户
     */
    private void cashBackHandle(double orderMoney, String sellerUserId, String outTradeNo, String cash_type) {
        MCashBackConfig thisMoneyConfig = getmCashBackConfig(orderMoney, outTradeNo, cash_type);
        if (null == thisMoneyConfig) return;
        List<FCashBackRecord> fCashBackRecords = fCashBackRecordService.findByUserId(sellerUserId);//用户当天返现记录
        int dayNumber = thisMoneyConfig.getDayNumber();
        int configId = thisMoneyConfig.getSid();
        int useDayNumber = 0;
        //过滤单配置笔数
        if (fCashBackRecords.size() > 0) {
            for (FCashBackRecord fCashBackRecord : fCashBackRecords) {
                if (configId == fCashBackRecord.getCid()) {
                    useDayNumber++;
                    if (useDayNumber >= dayNumber) {
                        logger.info(sellerUserId + "超出配置限制单数");
                        return;
                    }
                }
            }
            //控制返现总金额
            Double cashBackMoney = 0d;
            for (FCashBackRecord fCashBackRecord : fCashBackRecords) {
                cashBackMoney = cashBackMoney + fCashBackRecord.getCashBackMoney();
                if (cashBackMoney >= thisMoneyConfig.getDayMoney()) {
                    logger.info(sellerUserId + "超出配置返现总金额");
                    return;
                }
            }
            if (cashBackMoney + thisMoneyConfig.getCashBack() > thisMoneyConfig.getDayMoney()) {
                logger.info(sellerUserId + "此笔返现金额 超出配置返现总金额");
                return;
            }
        }
        //插入返现记录
        FCashBackRecord fCashBackRecord = new FCashBackRecord();
        fCashBackRecord.setCid(thisMoneyConfig.getSid());
        fCashBackRecord.setCashBackMoney(thisMoneyConfig.getCashBack());
        fCashBackRecord.setOrderMoney(orderMoney);
        fCashBackRecord.setOrderNo(outTradeNo);
        fCashBackRecord.setUserId(sellerUserId);
        fCashBackRecord.setCreateTime(new Date());
        fCashBackRecordService.insert(fCashBackRecord);
    }

    private MCashBackConfig getmCashBackConfig(double orderMoney, String outTradeNo, String cash_type) {
        MCashBackConfig thisMoneyConfig = mCashBackConfigService.findByOrderMoney(orderMoney, cash_type);//交易金额配置信息
        if (null == thisMoneyConfig) {
            logger.error("订单号" + outTradeNo + "订单金额" + orderMoney + "找不到对应返现配置");
            return null;
        }
        return thisMoneyConfig;
    }

    /**
     * 配件店-维修店
     *
     * @param orderMoney   订单金额
     * @param sellerUserId 收款方id
     * @param outTradeNo   订单号
     * @param cash_type    返现类型
     */
    private void sparepart2repair(double orderMoney, String sellerUserId, String outTradeNo, String cash_type) {
        MCashBackConfig thisMoneyConfig = getmCashBackConfig(orderMoney, outTradeNo, cash_type);
        if (null == thisMoneyConfig) return;
        List<FCashBackRecord> fCashBackRecords = fCashBackRecordService.findByUserId(sellerUserId);//用户当天返现记录
        int dayNumber = thisMoneyConfig.getDayNumber();
        int configId = thisMoneyConfig.getSid();
        int useDayNumber = 0;
        //过滤单配置笔数
        if (fCashBackRecords.size() > 0) {
            for (FCashBackRecord fCashBackRecord : fCashBackRecords) {
                if (configId == fCashBackRecord.getCid()) {
                    useDayNumber++;
                    if (useDayNumber >= dayNumber) {
                        return;
                    }
                }
            }
            //控制返现总金额
            Double cashBackMoney = 0d;
            for (FCashBackRecord fCashBackRecord : fCashBackRecords) {
                cashBackMoney = cashBackMoney + fCashBackRecord.getCashBackMoney();
                if (cashBackMoney >= thisMoneyConfig.getDayMoney()) {
                    return;
                }
            }
            if (cashBackMoney + thisMoneyConfig.getCashBack() > thisMoneyConfig.getDayMoney()) {
                return;
            }
        }
        //插入返现记录
        FCashBackRecord fCashBackRecord = new FCashBackRecord();
        fCashBackRecord.setCid(thisMoneyConfig.getSid());
        fCashBackRecord.setCashBackMoney(thisMoneyConfig.getCashBack());
        fCashBackRecord.setOrderMoney(orderMoney);
        fCashBackRecord.setOrderNo(outTradeNo);
        fCashBackRecord.setUserId(sellerUserId);
        fCashBackRecord.setCreateTime(new Date());
        fCashBackRecordService.insert(fCashBackRecord);
    }

    /**
     * 整车店-用户
     *
     * @param orderMoney   订单金额
     * @param sellerUserId 收款方id
     * @param outTradeNo   订单号
     * @param cash_type    返现类型
     */
    private void sale2User(double orderMoney, String sellerUserId, String outTradeNo, String cash_type) {
        MCashBackConfig thisMoneyConfig = getmCashBackConfig(orderMoney, outTradeNo, cash_type);
        if (null == thisMoneyConfig) return;

        List<FCashBackRecord> fCashBackRecords = fCashBackRecordService.findByUserId(sellerUserId);//用户当天返现记录
        int dayNumber = thisMoneyConfig.getDayNumber();
        int configId = thisMoneyConfig.getSid();
        int useDayNumber = 0;
        List<MPayment> paymentToday = findPaymentToday(sellerUserId);
        if (paymentToday.size() > 2) {
            logger.info(sellerUserId + "当天不是头两笔");
            return;
        }

        //过滤单配置笔数
        if (fCashBackRecords.size() > 0) {
            for (FCashBackRecord fCashBackRecord : fCashBackRecords) {
                if (configId == fCashBackRecord.getCid()) {
                    useDayNumber++;
                    if (useDayNumber >= dayNumber) {
                        return;
                    }
                }
            }
            //控制返现总金额
            Double cashBackMoney = 0d;
            double multiplyNoUp = BigDecimalUtil.getMultiplyNoUp(orderMoney, thisMoneyConfig.getCashBack());
            for (FCashBackRecord fCashBackRecord : fCashBackRecords) {
                cashBackMoney = cashBackMoney + fCashBackRecord.getCashBackMoney();
                if (cashBackMoney >= thisMoneyConfig.getDayMoney()) {
                    return;
                }
            }
            if (cashBackMoney + multiplyNoUp > thisMoneyConfig.getDayMoney()) {
                return;
            }
        }
        //插入返现记录
        FCashBackRecord fCashBackRecord = new FCashBackRecord();
        fCashBackRecord.setCid(thisMoneyConfig.getSid());
        fCashBackRecord.setCashBackMoney(BigDecimalUtil.getMultiplyNoUp(orderMoney, thisMoneyConfig.getCashBack()));
        fCashBackRecord.setOrderMoney(orderMoney);
        fCashBackRecord.setOrderNo(outTradeNo);
        fCashBackRecord.setUserId(sellerUserId);
        fCashBackRecord.setCreateTime(new Date());
        fCashBackRecordService.insert(fCashBackRecord);
    }


    @Override
    public SuperRecordModel countDayPayMent(SuperRecordModel superRecordModel) {
        return getSqlSession().selectOne("MPaymentMapper.countDayPayMent", superRecordModel);
    }

    @Override
    public boolean findByPayTradeNoCount(MPayment mPayment) {
        Long countNum = getSqlSession().selectOne("MPaymentMapper.findByPayTradeNoCount", mPayment);
        return countNum.intValue() == 0;
    }

    @Override
    public List<SuperRecordModel> getPaymentDayByUserId(SuperRecordModel srModel) {
        return getSqlSession().selectList("MPaymentMapper.getPaymentDayByUserId", srModel);
    }

    @Override
    public MPayment findPaymentByOutTradeNo(String out_trade_no) {
        return getSqlSession().selectOne("MPaymentMapper.findPaymentByOutTradeNo", out_trade_no);
    }

    @Override
    public MPayment findPaymentByOutTradeNoAndPayStatus(SuperRecordModel superRecordModel) {
        return getSqlSession().selectOne("MPaymentMapper.findPaymentByOutTradeNoAndPayStatus", superRecordModel);
    }


    @Override
    public void update(MPayment mPayment) {
        getSqlSession().update("MPaymentMapper.update", mPayment);
    }

    @Override
    public List<SuperRecordModel> getPayMentList(SuperRecordModel srModel) {
        return getSqlSession().selectList("MPaymentMapper.getPayMentList", srModel);
    }

    @Override
    public SuperRecordModel findPayMentByPayId(String pid) {
        return getSqlSession().selectOne("MPaymentMapper.findPayMentByPayId", pid);
    }

    @Override
    public MPayment findPaymentByOutTradeNoAndUserId(MPayment MPayment) {
        return getSqlSession().selectOne("MPaymentMapper.findPaymentByOutTradeNoAndUserId", MPayment);
    }

    @Override
    public Long countPayMent(SuperRecordModel srModel) {
        return getSqlSession().selectOne("MPaymentMapper.countPayMent", srModel);
    }

    @Override
    public List<SuperRecordModel> getNewPayMentList(SuperRecordModel srModel) {
        return getSqlSession().selectList("MPaymentMapper.getNewPayMentList", srModel);
    }

    @Override
    public List<MPayment> findPaymentAll(SuperRecordModel superRecordModel) {
        return getSqlSession().selectList("MPaymentMapper.findPaymentAll", superRecordModel);
    }

    @Override
    public MPayment findMPaymentByOrderId(String oid) {
        return getSqlSession().selectOne("MPaymentMapper.findMPaymentByOrderId", oid);
    }

    @Override
    public void updateMpayData(Date startTime) throws Exception {
        SuperRecordModel superRecordModel = new SuperRecordModel();
        if (null != startTime) {
            superRecordModel.put("startTime", startTime);
        }
        List<MPayment> list = findPaymentAll(superRecordModel);
        for (MPayment mPayment : list) {
            if ("WXPAY".equals(mPayment.getMchType())) {
                FBill fBill = new FBill();
                fBill.setSid(SequenceUtil.Serial("DD"));
                fBill.setOutTradeNo(mPayment.getOutTradeNo());
                fBill.setAddTime(new Date());
                Map<Object, String> store = null;
                boolean flag = true;//标识那个判断出错
                String outTradeNo = mPayment.getOutTradeNo();
                String payTradeNo = mPayment.getPayTradeNo();
                if (mPayment.getPayType().equals("TRANSFER")) {
                    User user = userService.getUserBySid(mPayment.getBuyerUserId());
                    if (user == null) {
                        store = WxPayUtil.getUserWxOrderInfo(outTradeNo, payTradeNo, "transfer");
                    } else {
                        store = WxPayUtil.getUserWxOrderInfo(outTradeNo, payTradeNo, "user");
                    }
                } else {
                    if (outTradeNo.contains("Co")) {
                        store = WxPayUtil.getUserWxOrderInfo(outTradeNo, payTradeNo, "store");
                    } else {
                        flag = false;
                        store = WxPayUtil.getUserWxOrderInfo(outTradeNo, payTradeNo, "user");
                    }
                    if ("FAIL".equals(store.get("result_code"))) {
                        if (flag) {
                            store = WxPayUtil.getUserWxOrderInfo(outTradeNo, payTradeNo, "user");
                        } else {
                            store = WxPayUtil.getUserWxOrderInfo(outTradeNo, payTradeNo, "store");
                        }
                    }
                }
                fBill.setPayTradeNo(store.get("transaction_id"));
                fBill.setExtra(JSON.toJSONString(store));
                Double payMoney = Double.valueOf(AmountUtils.changeF2Y(store.get("total_fee").toString()));
                fBill.setMoney(payMoney);
                fBill.setNickname(store.get("openid"));
                String attach = store.get("attach");
                Map param = JsonUtils.toMap(attach);
                String couponId = "";
                String brokerage = "";
                if (param.containsKey("coupon_id")) {
                    if (!StringUtils.isEmpty((String) param.get("coupon_id"))) {
                        couponId = param.get("coupon_id").toString();
                    }
                } else if (param.containsKey("cid")) {
                    if (!StringUtils.isEmpty((String) param.get("cid"))) {
                        couponId = param.get("cid").toString();
                    }
                }
                if (param.containsKey("bro")) {
                    brokerage = param.get("bro").toString();
                } else if (param.containsKey("brokerage")) {
                    brokerage = param.get("brokerage").toString();
                }

                if (!(StringUtils.isEmpty(brokerage) && StringUtils.isEmpty(couponId))) {
                    mPayment.setCouponId(couponId);
                    if (StringUtils.isEmpty(brokerage)) {
                        brokerage = "0";
                    }
                    double brokerage1 = Double.parseDouble(brokerage);
                    mPayment.setBrokerage(brokerage1);
                    fBill.setBrokerage(brokerage1);
                    fBill.setCouponId(couponId);
                }
                if ("Service".equals(mPayment.getPayType())) {
                    mPayment.setPayActualMoney(payMoney);
                } else {
                    mPayment.setPayActualMoney(mPayment.getPayMoney());
                }
                update(mPayment);
                fBillService.insert(fBill);
            } else if ("ALIPAY".equals(mPayment.getMchType())) {
                AlipayTradeQueryResponse alipayTradeQueryResponse = AliPayUtil.getAliPayQuery(mPayment.getPayTradeNo());
                FBill fBill = new FBill();
                fBill.setSid(SequenceUtil.Serial("DD"));
                fBill.setPayTradeNo(alipayTradeQueryResponse.getTradeNo());
                fBill.setOutTradeNo(alipayTradeQueryResponse.getOutTradeNo());
                String body = alipayTradeQueryResponse.getBody();
                Map attach = JsonUtils.toMap(body);
                String couponId = "";
                String brokerage = "";
                if (attach.containsKey("coupon_id")) {
                    couponId = attach.get("coupon_id").toString();
                }
                if (attach.containsKey("brokerage")) {
                    brokerage = attach.get("brokerage").toString();
                }
                fBill.setCouponId(couponId);
                if (!(StringUtils.isEmpty(couponId) && StringUtils.isEmpty(brokerage))) {
                    mPayment.setCouponId(couponId);
                    double brokerage1 = Double.parseDouble(brokerage);
                    mPayment.setBrokerage(brokerage1);
                    fBill.setBrokerage(brokerage1);
                }
                if ("Service".equals(mPayment.getPayType())) {
                    String totalAmount = alipayTradeQueryResponse.getTotalAmount();
                    double payActualMoney = Double.parseDouble(totalAmount);
                    mPayment.setPayActualMoney(payActualMoney);
                    fBill.setMoney(payActualMoney);
                } else {
                    mPayment.setPayActualMoney(mPayment.getPayMoney());
                    String totalAmount = alipayTradeQueryResponse.getTotalAmount();
                    double payActualMoney = Double.parseDouble(totalAmount);
                    fBill.setMoney(payActualMoney);
                }
                fBill.setNickname(alipayTradeQueryResponse.getBuyerLogonId());
                fBill.setAddTime(new Date());
                fBill.setExtra(JSON.toJSONString(alipayTradeQueryResponse));
                fBillService.insert(fBill);
                update(mPayment);

            }
        }
    }

    @Override
    public List<MPayment> findAllData() {
        return getSqlSession().selectList("MPaymentMapper.findAllData");
    }

    @Override
    public void updateMPayMent(MPayment mPayment) {
        getSqlSession().update("MPaymentMapper.updateMPayMent", mPayment);
    }

    @Override
    public Double getLastMonthBySellUserId(String seller_user_id) {
        return getSqlSession().selectOne("MPaymentMapper.getLastMonthBySellUserId", seller_user_id);
    }

    @Override
    public List<MPayment> findPaymentToday(String seller_user_id) {
        return getSqlSession().selectList("MPaymentMapper.findPaymentToday", seller_user_id);
    }
}
